﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Controls;

using Nui = Microsoft.Research.Kinect.Nui;
using Microsoft.Research.Kinect.Nui;

namespace MSUS.Kinect.SkeletonTracker
{
	/// <summary>
	/// a list of loaded Gestures for realtime tracking
	/// </summary>
	public class GestureList
	{
		private IList<JointPositionHistory> _gestures;
		public float Tolerance { get; set; }
		/// <summary>
		/// set this to false to only allow one copy of a given gesture name
		/// if this is true it will allow multiple gesture definitions to be loaded against a name
		/// this can be used to make gestures easier to recognise
		/// </summary>
		public bool AllowMultipleIdenticalGestures { get; set; }

		public GestureList()
		{
			Tolerance = 0.25f;
			AllowMultipleIdenticalGestures = true;
			_gestures = new List<JointPositionHistory>();
		}

		/// <summary>
		/// load a gesture from a file.
		/// </summary>
		/// <param name="gestureFilePath"></param>
		public void LoadGesture(string gestureFilePath)
		{
			if (File.Exists(gestureFilePath))
			{
				JointPositionHistory gesture;
				using (StreamReader sr = new StreamReader(gestureFilePath))
				{
					gesture = JointPositionHistory.LoadPositionHistory(sr);
					if (gesture != null)
					{
						if (!AllowMultipleIdenticalGestures)
						{
							RemoveGesture(gesture.GestureName);
						}
						_gestures.Add(gesture);
					}
				}
			}
		}

		public void ClearGestures()
		{
			while (_gestures.Count > 0)
				_gestures.RemoveAt(0);
		}

		public void RemoveGesture(string gestureName)
		{
			while (_gestures.FirstOrDefault(i => i.GestureName == gestureName) != null)
			{
				_gestures.Remove(_gestures.FirstOrDefault(i => i.GestureName == gestureName));
			}
		}

		/// <summary>
		/// renders all loaded gestures onto a canvas (requires 
		/// </summary>
		/// <param name="canvas"></param>
		/// <param name="windowWidth"></param>
		/// <param name="windowHeight"></param>
		public void RenderGestures(Canvas canvas, int windowWidth, int windowHeight)
		{
			foreach (JointPositionHistory gesture in _gestures)
			{
				gesture.RenderPath(canvas, windowWidth, windowHeight);
			}
		}


		private DateTime _lastGestureTrigger;
		private string _lastGesture;

		public bool CheckGestures(SkeletonPositionHistory skeletonHistory, out string gestureName)
		{
			gestureName = "";
			TimeSpan timeSinceLastTrigger = DateTime.Now - _lastGestureTrigger;

			foreach (JointPositionHistory gesture in _gestures)
			{
				if (timeSinceLastTrigger.TotalSeconds > 2 || gesture.GestureName != _lastGesture)	//	only record gestures once every 2 seconds
				{

					if (skeletonHistory.GetJointHistory(gesture.JointId).CompareForGesture(gesture, skeletonHistory.NeckVector, Tolerance))
					{
						gestureName = gesture.GestureName;
						_lastGestureTrigger = DateTime.Now;
						_lastGesture = gestureName;
						return true;
					}
				}
			}
			return false;
		}
	}
}
